#!bash
#
# bash completion file for core kubecfg commands
#
# This script provides completion of non replication controller options
#
# To enable the completions either:
#  - place this file in /etc/bash_completion.d
#  or
#  - copy this file and add the line below to your .bashrc after
#    bash completion features are loaded
#     . kubecfg
#
# Note:
# Currently, the completions will not work if the kube-apiserver daemon is not
# running on localhost on the standard port 8080

__contains_word () {
    local w word=$1; shift
    for w in "$@"; do
        [[ $w = "$word" ]] && return
    done
    return 1
}

# This should be provided by the bash-completions, but give a really simple
# stoopid version just in case.  It works most of the time.
if ! declare -F _get_comp_words_by_ref >/dev/null 2>&1; then
_get_comp_words_by_ref ()
{
    while [ $# -gt 0 ]; do
        case "$1" in
        cur)
            cur=${COMP_WORDS[COMP_CWORD]}
            ;;
        prev)
            prev=${COMP_WORDS[COMP_CWORD-1]}
            ;;
        words)
            words=("${COMP_WORDS[@]}")
            ;;
        cword)
            cword=$COMP_CWORD
            ;;
        -n)
            shift # we don't handle excludes
            ;;
        esac
        shift
    done
}
fi


__has_service() {
    local i
    for ((i=0; i < cword; i++)); do
        local word=${words[i]}
        # strip everything after a / so things like pods/[id] match
        word=${word%%/*}
        if __contains_word "${word}" "${services[@]}" &&
           ! __contains_word "${words[i-1]}" "${opts[@]}"; then
            return 0
        fi
    done
    return 1
}

# call kubecfg list $1,
# exclude blank lines
# skip the header stuff kubecfg prints on the first 2 lines
# append $1/ to the first column and use that in compgen
__kubecfg_parse_list()
{
    local kubecfg_output
    if kubecfg_output=$(kubecfg list "$1" 2>/dev/null); then
        out=($(echo "${kubecfg_output}" | awk -v prefix="$1" '/^$/ {next} NR > 2 {print prefix"/"$1}'))
        COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) )
    fi
}

_kubecfg_specific_service_match()
{
    case "$cur" in
        pods/*)
            __kubecfg_parse_list pods
            ;;
        minions/*)
            __kubecfg_parse_list minions
            ;;
        replicationControllers/*)
            __kubecfg_parse_list replicationControllers
            ;;
        services/*)
            __kubecfg_parse_list services
            ;;
        *)
            if __has_service; then
                return 0
            fi
            compopt -o nospace
            COMPREPLY=( $( compgen -S / -W "${services[*]}" -- "$cur" ) )
            ;;
    esac
}

_kubecfg_service_match()
{
    if __has_service; then
        return 0
    fi

    COMPREPLY=( $( compgen -W "${services[*]}" -- "$cur" ) )
}

_kubecfg()
{
    local opts=(
            -h
            -c
    )
    local create_services=(pods replicationControllers services)
    local update_services=(replicationControllers)
    local all_services=(pods replicationControllers services minions)
    local services=("${all_services[@]}")

    local json_commands=(create update)
    local all_commands=(create update get list delete stop rm rollingupdate resize)
    local commands=("${all_commands[@]}")

    COMPREPLY=()
    local command
    local cur prev words cword
    _get_comp_words_by_ref -n : cur prev words cword

    if __contains_word "$prev" "${opts[@]}"; then
        case $prev in
            -c)
                _filedir '@(json|yml|yaml)'
                return 0
                ;;
            -h)
                return 0
                ;;
        esac
    fi

    if [[ "$cur" = -* ]]; then
        COMPREPLY=( $(compgen -W "${opts[*]}" -- "$cur") )
        return 0
    fi

    # if you passed -c, you are limited to create or update
    if __contains_word "-c" "${words[@]}"; then
        services=("${create_services[@]}" "${update_services[@]}")
        commands=("${json_commands[@]}")
    fi

    # figure out which command they are running, remembering that arguments to
    # options don't count as the command!  So a hostname named 'create' won't
    # trip things up
    local i
    for ((i=0; i < cword; i++)); do
        if __contains_word "${words[i]}" "${commands[@]}" &&
           ! __contains_word "${words[i-1]}" "${opts[@]}"; then
            command=${words[i]}
            break
        fi
    done

    # tell the list of possible commands
    if [[ -z ${command} ]]; then
        COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
        return 0
    fi

    # remove services which you can't update given your command
    if [[ ${command} == "create" ]]; then
        services=("${create_services[@]}")
    elif [[ ${command} == "update" ]]; then
        services=("${update_services[@]}")
    fi

    case $command in
        create | list)
            _kubecfg_service_match
            ;;
        update | get | delete)
            _kubecfg_specific_service_match
            ;;
        *)
            ;;
    esac

    return 0
}

complete -F _kubecfg kubecfg
# ex: ts=4 sw=4 et filetype=sh
